-- SPDX-License-Identifier: GPL-3.0-or-later
---@class KJobj: Object
local KJobj = class("KJobj")
local U = require "packages/utility/utility"
-- local ShopMgr = require "packages/lang/ShopMgr"

function KJobj:initialize(data)
  self.nextBattleData = data.nextBattleData
  self.istest = data.istest
  self.maxplayers = data.maxplayers or 4
  self.rebles = data.rebles or 4
  self.upMarks = data.upMarks or {"@drcdnum","@handsmax","@slashadd","@slashtar","@shieldadd"}
end
--准备开始逻辑
function KJobj:logic_prepareForStart(data)
  local room = Fk:currentRoom()
  local players = room.players
  room.logic:addTriggerSkill(GameRule)
  for _, trig in ipairs(Fk.global_trigger) do
    room.logic:addTriggerSkill(trig)
  end
  room:sendLog{ type = "$GameStart" }
  for _,da in ipairs(data.otherbanners) do
    room:setBanner(da[1],da[2])
  end
end
--准备抽牌堆
function KJobj:logic_prepareDrawPile(data)
  local room = Fk:currentRoom()
  --重新过滤卡组
  local filterCardIds = {}
  local excepts = data.excepts
  local whitecards = data.whitecards
  local allCardIds = Fk:getAllCardIds()
  for i = 1, #allCardIds do
    local id = allCardIds[i]
    local card = Fk:getCardById(id)
    if card then
      if card.is_derived then
        table.insert(room.void, id)
        room:setCardArea(id, Card.Void, nil)
      else
        if table.contains(whitecards,card.package.name) then
          if not table.contains(excepts,card.trueName) then
            table.insert(filterCardIds,id)
          end
        end
      end
    end
  end
  table.shuffle(filterCardIds)
  room.draw_pile = filterCardIds
  for _, id in ipairs(room.draw_pile) do
    room:setCardArea(id, Card.DrawPile, nil)
  end
end
--准备标记身份
function KJobj:logic_assignRoles(data)
  local room = Fk:currentRoom()
  local n = #room.players
  local roles = data.role_table[n]
  table.shuffle(roles)
  local bots_t = {}
  local players_t = {}
  for i = 1, n do
    local p = room.players[i]
    if p.id < 0 then
      table.insert(bots_t,{p.id,i})
    else
      table.insert(players_t,{p.id,i})
    end
  end
  local randplayer = room.players[table.random(players_t)[2]]
  randplayer.role = "lord"
  randplayer.role_shown = true
  room:broadcastProperty(randplayer, "role")

  local rebles = self.rebles or 4
  local seecampcards = {"lord","loyalist"}
  for i = 1, n do
    local p = room.players[i]
    if p.role ~= "lord" then
      if p.id < 0 and rebles > 0 then
        p.role = "rebel"
        rebles = rebles - 1
      else
        p.role = "loyalist"
      end
      p.role_shown = true
      room:broadcastProperty(p,"role")
    end
  end
  for i = 1, n do
    local p = room.players[i]
    if table.contains(seecampcards,p.role) then
      for _,pr in ipairs(room.players) do
        if p ~= pr and table.contains(seecampcards,pr.role) then
          -- table.insert(p.buddy_list,pr.id)
          p:addBuddy(pr)
        end
      end
    end
  end
  -- p(table.map(room.players,function(pr) return pr.buddy_list end))
  -- dbg()
end
--每轮开始
function KJobj:roundStart()
  --先登制敌判断
  local room = Fk:currentRoom()
  if #self.nextBattleData == 0 then return end
  local curbattledata = self.nextBattleData[room:getTag('@curturn')]
  local curxiandengnum = room:getTag("curxiandengnum") or 0
  if curbattledata.xiandengnum < 1 or curxiandengnum >= curbattledata.xiandengnum then
    return
  end
  curxiandengnum = curxiandengnum + 1
  room:setTag("curxiandengnum",curxiandengnum)

  local getbuff = GensLimts:getKJRandBuffs()[room.settings.gameMode]
  if not getbuff or #getbuff == 0 then return end
  -- getbuff = table.clone(getbuff)
  -- if curxiandengnum > room:getTag('@battleturn') - 2 then
  --   table.insert(getbuff,"zhongzhanSkill")
  -- end
  -- getbuff = {"mb_huwei", "mb_huwei", "mb_huwei","mb_huwei", "mb_huwei", "mb_huwei","mb_huwei", "mb_huwei", "mb_huwei"}
  getbuff = table.random(getbuff,#getbuff)

  local players = table.filter(room.alive_players,function(pr) return pr.role ~= "rebel" end)
  for _, p in ipairs(players) do
    local choices = {}
    for i =1,3 do
      if #getbuff > 0 and not p:hasSkill(getbuff[1]) then
        table.insert(choices,table.remove(getbuff,1))
      end        
    end    
    if #choices > 0 then
      p.request_data = json.encode({ choices, choices, "#roundchc", "#roundchc", true })    
    end  
  end

  room:notifyMoveFocus(players, "AskForChoice")
  room:doBroadcastRequest("AskForChoice", players)
  local yilao_pid
  local selchcinfo = {}
  for i, pr in ipairs(players) do
    if pr.client_reply == "yilaoSkill" and i ~= #players then
      yilao_pid = pr.id
    else
      table.insert(selchcinfo,{id=pr.id,chs=pr.client_reply})
    end
  end
  if yilao_pid then
    table.insert(selchcinfo,{id=yilao_pid,chs="yilaoSkill"})
  end
  for _, info in ipairs(selchcinfo) do
    local pr = room:getPlayerById(info.id)
    room:handleAddLoseSkills(pr,info.chs,nil,false)
  end
end
--清理武将
function KJobj:refreshBury(pr)
  if pr.id < 0 then
    pr:bury()
  else
    pr:setCardUseHistory("")
    -- pr:setSkillUseHistory("")
    pr:throwAllCards()
    -- pr:throwAllMarks()
    pr:clearPiles()
    pr:reset()
  end
end
--更新
function KJobj:upRobots(pr,battledata)
  local room = pr.room
  local getcardnum = battledata.getcardnum
  local getmaxhp = battledata.getmaxhp
  local getshield = battledata.getshield
  local getsameskills = battledata.getsameskills
  local rongzhuangnum = battledata.rongzhuangnum
  local deadthsing = battledata.deadthsing
  local skillname = "#norkj_rule"
  local isextradraws = true
  -- if #room.aiselgens == 0 then 
  --   print("=====人机选将池没了，判定主公胜利=====")
  --   return room:gameOver("") 
  -- end
  local aigens = room.aiselgens
  if #aigens == 0 then return end
  if pr.dead then
    if pr.role == "rebel" then
      local generalskills = pr:getAllSkills()
      if #generalskills > 0 then
        local loseskills = ""
        for _,s in ipairs(generalskills) do
          loseskills = loseskills.."-"..s.name.."|"
        end
        room:handleAddLoseSkills(pr, loseskills, nil, false)
      end
      room:changeHero(pr, table.remove(aigens,1), true, false, true)
    else
      isextradraws = false
      room:drawCards(pr,4,skillname)
    end
    -- room:revivePlayer(pr, false)
    room:setPlayerProperty(pr, "dead", false)
    pr._splayer:setDied(false)
    room:setPlayerProperty(pr, "dying", false)
    room:setPlayerProperty(pr, "hp", pr.role == "rebel" and pr.maxHp or math.min(2,pr.maxHp))
    table.insertIfNeed(room.alive_players, pr)
    room:sendLog { type = "#Revive", from = pr.id }
    room.logic:trigger(fk.AfterPlayerRevived, pr, { reason = "" })
  else
    if pr.role ~= "rebel" and pr:isWounded() and room:getTag("no_recover") ~= 1 then
      room:recover({who = pr,num = 2,skillName = skillname})
    end
  end
  if rongzhuangnum and rongzhuangnum[pr.role] then
    pr.rongzhuangnum = rongzhuangnum[pr.role]
  end
  local addmaxhp = getmaxhp and getmaxhp[pr.role]
  if addmaxhp then
    pr.hp = pr.hp + addmaxhp
    pr.maxHp = pr.maxHp + addmaxhp
    room:setPlayerProperty(pr, "hp", pr.hp)
    room:setPlayerProperty(pr, "maxHp", pr.maxHp)
  end
  local addcardnum = getcardnum and getcardnum[pr.role]
  if addcardnum and isextradraws then
    room:drawCards(pr,addcardnum,skillname)
  end
  local addshield = getshield and getshield[pr.role]
  if addshield then
    pr.shield = pr.shield + addshield
    room:setPlayerProperty(pr, "shield", pr.shield)
  end
  local addskills = getsameskills and getsameskills[pr.role]
  if addskills then
    addskills = table.concat(addskills,"|")
    room:handleAddLoseSkills(pr,addskills,nil,false)
  end
  if deadthsing then
    local adddeathskills = deadthsing[pr.role]
    if adddeathskills and #adddeathskills > 0 then
      if adddeathskills[1] > 0 then
        room:handleAddLoseSkills(pr,"kj_wangyu",nil,false)
      end
      table.remove(adddeathskills,1)
    end
  end
end
--标记测试
function KJobj:testMark(nextvalue)
  local room = Fk:currentRoom()
  if nextvalue == 1 then
    for _,mark in pairs(self.upMarks) do
      local addv = 1
      if mark == "@slashtar" then
        room.players[1].slashtarmark = {addv,addv}
      end
      room:setPlayerMark(room.players[1],mark,addv)
    end
  end
end
--更新下一轮
function KJobj:upNextTurn(nextvalue)
  local room = Fk:currentRoom()
  if #self.nextBattleData == 0 then return end
  local battledata = table.clone(self.nextBattleData[nextvalue])
  if battledata.deadthsing then
    local deadthsing = {}
    for role,v in pairs(battledata.deadthsing) do
      deadthsing[role] = table.random(v,#v)
    end
    battledata.deadthsing = deadthsing
  end
  if battledata.bossgens then
    local bossindex = math.random(1,3)
    table.insert(room.aiselgens,bossindex,table.random(battledata.bossgens))
  end
  -- if self.istest then
  --   self:testMark(nextvalue)
  -- end
  for _,pr in ipairs(room.players) do
    self:upRobots(pr,battledata)
  end
end
--武将死亡前
function KJobj:buryVictim(who)
  local room = Fk:currentRoom()
  room:setTag("SkipGameRule", true)
  room:setTag("SkipNormalDeathProcess", true)
  local tar = room:getPlayerById(who)
  self:refreshBury(tar)
end
--游戏开始
function KJobj:gameStart()
  local room = Fk:currentRoom()
  local players = {}
  for _,pr in ipairs(room.alive_players) do
    if pr.id > 0 then
      table.insert(players,pr)
      -- room:handleAddLoseSkills(player,"hunjiang",nil,false)
    end
  end
  if #players > self.maxplayers then
    room:doBroadcastNotify("ShowToast", "游戏玩家超过规定人数，游戏结束")
    return room:gameOver("")
  end
  room:setTag("no_recover",1)
  self:upNextTurn(room:getTag('@curturn'))
  room:setTag("no_recover",0)
  for _,pr in ipairs(room.players) do
    if pr.id > 0 and pr.seeskin then
      local gen = Fk.generals[pr.general]
      local truename = gen.trueName
      local skinconfig = GensLimts:getseseGens()[truename]
      if skinconfig then
        local skins = table.clone(skinconfig.skin)
        table.insert(skins,pr.general)
        U.setPrivateMark(pr, "&skingens", skins)
        room.seeskinman = true
        room:handleAddLoseSkills(pr,"skinchange",nil,false)
      end
    end
  end
end
--起手牌
function KJobj:drawInitialCards(data)
  local room = Fk:currentRoom()
  data.num = data.num + room:getTag("rebotdrawnum")
end
--游戏准备阶段
function KJobj:gamePrepared()
  local room = Fk:currentRoom()
  local rebotdrawnum = math.floor(room.settings.luckTime / 5 ) 
  if rebotdrawnum > 0 then
    room:doBroadcastNotify("ShowToast", "房间".."<font color='red'><b>手气卡</b></font>".."越多，反贼起手手牌越多")
    room:setTag("rebotdrawnum",rebotdrawnum)
  end
end
--游戏规则判定
function KJobj:gameOverJudge()
  local room = Fk:currentRoom()
  room:setTag("SkipGameRule", true)
end
--死亡后
function KJobj:deaThed(who,getrewards)
  local room = Fk:currentRoom()
  local tar = room:getPlayerById(who)
  local ispass = table.every(room.alive_players,function(pr) return not GensLimts:isSameCamp(pr,tar) end)
  if not ispass then return end

  local haslord = room:getLord()
  local victoryrole = tar.role == "rebel" and (haslord and "lord" or "loyalist") or "rebel"
  if victoryrole ~= "rebel" then
    local cur_turn = room:getTag('@curturn')
    cur_turn = cur_turn + 1
    if cur_turn > room:getTag('@battleturn') then
      room:gameOver(victoryrole)
    else
      room:setTag('@curturn',cur_turn)
      room:setTag("curxiandengnum",0)
      room:setBanner("@totalbattle",cur_turn.."/"..room:getTag('@battleturn'))
      self:upNextTurn(cur_turn)
      if getrewards then
        self:roundStart()
      end
    end
  else
    room:gameOver(victoryrole)
  end
end
--欸嘿嘿
function KJobj:changeSkin(player,gen)
  local room = Fk:currentRoom()
  local originskin = player.general
  -- p(Fk:translate("~"..originskin))
  -- player:chat(Fk:translate("~"..originskin))
  if not string.startsWith(originskin,"skin") then
    player.originskin = originskin
  end
  player.general = gen
  -- room:broadcastProperty(player, "general")
  for _, p in ipairs(room.players) do
    if p.seeskin then
      room:notifyProperty(p, player, "general")
    end
  end
end

--可以看
function KJobj:HpChangedEvt(player)
  local gen = Fk.generals[player.general]
  local truename = gen.trueName
  local skingen = GensLimts:getseseGens()[truename]
  if skingen then
    if player.hp <= 0 and player.originskin then
      player:chat(Fk:translate("~"..player.originskin))
      player.room:broadcastPlaySound("./packages/" + Fk.generals[player.originskin].package.extensionName + "/audio/death/" + player.originskin)
    end
    if player.hp <= skingen.hp and not string.startsWith(player.general,"skin") then
      return table.random(skingen.skin)
    end
    if player.hp > skingen.hp and string.startsWith(player.general,"skin") and player.originskin then
      return player.originskin
    end
  end    
end

return KJobj
